<template>
  <div class="ocr-demo">
    <h2>TensorFlow.js OCR Demo</h2>
    
    <div class="upload-section">
      <input 
        type="file" 
        accept="image/*" 
        @change="handleImageUpload" 
        ref="fileInput"
        class="file-input"
      />
      <button @click="triggerFileInput" class="upload-btn">选择图片</button>
      <button @click="loadOCR" :disabled="ocrLoading" class="model-btn">
        {{ ocrLoading ? 'OCR引擎加载中...' : '加载OCR引擎' }}
      </button>
    </div>

    <div class="image-preview" v-if="imageSrc">
      <h3>预览图片</h3>
      <img :src="imageSrc" alt="Preview" class="preview-image" ref="previewImage" />
    </div>

    <div class="ocr-result" v-if="ocrResult !== null">
      <h3>OCR 识别结果</h3>
      <div class="result-content">
        <p v-if="ocrResult.loading">正在识别中...</p>
        <p v-else-if="ocrResult.error">识别出错: {{ ocrResult.error }}</p>
        <div v-else>
          <p>识别文本:</p>
          <div class="recognized-text">{{ ocrResult.text }}</div>
        </div>
      </div>
    </div>

    <button 
      @click="performOCR" 
      :disabled="!imageSrc || isProcessing || !ocrReady" 
      class="ocr-btn"
      v-if="imageSrc"
    >
      {{ isProcessing ? '识别中...' : '开始OCR识别' }}
    </button>
    
    <div v-if="ocrLoading" class="loading-info">
      OCR引擎加载中，请稍候... (首次加载可能需要较长时间)
    </div>
  </div>
</template>

<script setup lang='ts'>
import { ref } from 'vue';

// 动态导入 Tesseract.js
let Tesseract: any = null;
let ocrWorker: any = null;

const fileInput = ref<HTMLInputElement | null>(null);
const imageSrc = ref<string | null>(null);
const previewImage = ref<HTMLImageElement | null>(null);
const ocrResult = ref<{ text?: string; loading?: boolean; error?: string } | null>(null);
const isProcessing = ref(false);
const ocrReady = ref(false);
const ocrLoading = ref(false);

// 触发文件选择
const triggerFileInput = () => {
  fileInput.value?.click();
};

// 处理图片上传
const handleImageUpload = (event: Event) => {
  const input = event.target as HTMLInputElement;
  if (input.files && input.files[0]) {
    const file = input.files[0];
    const reader = new FileReader();
    
    reader.onload = (e) => {
      imageSrc.value = e.target?.result as string;
      ocrResult.value = null; // 重置之前的识别结果
    };
    
    reader.readAsDataURL(file);
  }
};

// 加载 OCR 引擎
const loadOCR = async () => {
  ocrLoading.value = true;
  try {
    console.log('开始加载Tesseract.js...');
    
    // 动态导入 Tesseract.js
    Tesseract = await import('tesseract.js');
    console.log('Tesseract.js已加载',Tesseract);
    // 创建OCR工作者
    ocrWorker = Tesseract.createWorker();
    
    // 加载并初始化
    await ocrWorker.load();
    await ocrWorker.loadLanguage('eng');
    await ocrWorker.initialize('eng');
    
    ocrReady.value = true;
    console.log('OCR引擎加载完成');
  } catch (error) {
    console.error('OCR引擎加载失败:', error);
    ocrResult.value = { error: 'OCR引擎加载失败: ' + (error as Error).message };
  } finally {
    ocrLoading.value = false;
  }
};

// OCR 识别
const performOCR = async () => {
  if (!previewImage.value || !ocrReady.value || !ocrWorker) return;
  
  isProcessing.value = true;
  ocrResult.value = { loading: true };
  
  try {
    const result = await realOCRRecognition(previewImage.value);
    ocrResult.value = { text: result };
  } catch (error) {
    console.error('OCR识别错误:', error);
    ocrResult.value = { error: (error as Error).message || '识别失败' };
  } finally {
    isProcessing.value = false;
  }
};

// 使用 Tesseract.js 进行 OCR 识别
const realOCRRecognition = async (imageElement: HTMLImageElement): Promise<string> => {
  try {
    // 使用 Tesseract.js 进行 OCR 识别
    const result = await ocrWorker.recognize(imageElement);
    return result.data.text;
  } catch (error) {
    throw error;
  }
};
</script>

<style scoped lang='less'>
.ocr-demo {
  padding: 20px;
  max-width: 800px;
  margin: 0 auto;
}

.upload-section {
  margin-bottom: 20px;
  display: flex;
  gap: 10px;
  align-items: center;
  
  .file-input {
    display: none;
  }
  
  .upload-btn, .model-btn {
    background-color: #42b983;
    color: white;
    border: none;
    padding: 10px 20px;
    border-radius: 4px;
    cursor: pointer;
    
    &:hover:not(:disabled) {
      background-color: #359c6d;
    }
    
    &:disabled {
      background-color: #a0cfff;
      cursor: not-allowed;
    }
  }
  
  .model-btn {
    background-color: #6772e5;
    
    &:hover:not(:disabled) {
      background-color: #5a67d8;
    }
  }
}

.image-preview {
  margin-bottom: 20px;
  
  .preview-image {
    max-width: 100%;
    max-height: 400px;
    border: 1px solid #ddd;
    border-radius: 4px;
  }
}

.ocr-result {
  margin-bottom: 20px;
  
  .result-content {
    min-height: 50px;
    padding: 15px;
    background-color: #f5f5f5;
    border-radius: 4px;
    
    .recognized-text {
      font-size: 16px;
      color: #333;
      white-space: pre-wrap;
      line-height: 1.5;
    }
  }
}

.ocr-btn {
  background-color: #409eff;
  color: white;
  border: none;
  padding: 12px 24px;
  border-radius: 4px;
  cursor: pointer;
  margin-bottom: 20px;
  
  &:disabled {
    background-color: #a0cfff;
    cursor: not-allowed;
  }
  
  &:not(:disabled):hover {
    background-color: #66b1ff;
  }
}

.loading-info {
  color: #666;
  font-style: italic;
  margin-bottom: 20px;
}

h3 {
  margin-top: 0;
}
</style>